\begin{Exercise}[title={方法调用},difficulty=2]
\label{ex:methodcalls}
\Question \label{ex:methodcalls q1} 假设有下面的程序。
要注意的是包 \package{container/vector} 曾经是 Go 的一部分，但是当内建的
\func{append} 出现后，就被移除了。
然而，对于当前的问题这不重要。这个包实现了有 push 和 pop 方法的栈结构。

\begin{lstlisting}
package main

import "container/vector"

func main() {
	k1 := vector.IntVector{}
	k2 := &vector.IntVector{}
	k3 := new(vector.IntVector)
	k1.Push(2)
	k2.Push(3)
	k3.Push(4)
}
\end{lstlisting}
\var{k1}，\var{k2} 和 \var{k3} 的类型是什么？

\Question 当前，这个程序可以编译并且运行良好。在不同类型的变量上 \func{Push}
都可以工作。\func{Push} 的文档这样描述：
\begin{quote}
func (p *IntVector) Push(x int)
Push 增加 x 到向量的末尾。
\end{quote}
那么接受者应当是 \type{*IntVector} 类型，为什么上面的代码（Push 语句）可以正确工作？
above (the Push statements) work correct then?

\end{Exercise}

\begin{Answer}
\Question \var{k1} 的类型是 \type{vector.IntVector}。为什么？
这里使用了符号 \verb|{}|，因此获得了类型的值。
变量 \var{k2} 是 \type{*vector.IntVector}，因为获得了复合语句的地址（\verb|&|）。
而最后的 \var{k3} 同样是 \type{*vector.IntVector} 类型，因为 \func{new}
返回该类型的指针。

\Question 在 \cite{go_spec} 的``调用''章节，有这样的描述：
\begin{quote}
当 \var{x} 的方法集合包含 \func{m}，
并且参数列表可以赋值给 \func{m} 的参数，方法调用 \func{x.m()} 是合法的。
如果 \var{x} 可以被地址化，而 \var{\&x} 的方法集合包含 \func{m}，
\func{x.m()} 可以作为 \func{(\&x).m()} 的省略写法。
\end{quote}
换句话说，由于 \var{k1} 可以被地址化，而 \type{*vector.IntVector}
\emph{具有} \func{Push} 方法，调用 \lstinline{k1.Push(2)} 被 Go 转换为 
\lstinline{(&k1).Push(2)} 来使型系统愉悦（也使你愉悦——现在你已经了解到这一点）。
\footnote{参阅本章的第 ``\titleref{sec:methods}'' 节。}

\end{Answer}
